﻿#ifdef _MSC_VER
    #define _CRT_SECURE_NO_WARNINGS     // 禁用 MSVC 的安全警告
#endif
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 参考学习网站：https://zh.cppreference.com/w/cpp
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170
// OpenGl 学习网站：https://docs.gl/
#include "common.h" // 包含预编译头文件
#include "FFmpegTranscoding.h"

PcmFormat transcode_pcm;

AudioTranscoder::AudioTranscoder(const std::string& input_filename, const std::string& output_filename) :
    input_format_context(nullptr),
    output_format_context(nullptr),
    input_codec_context(nullptr),
    output_codec_context(nullptr),
    input_stream(nullptr),
    output_stream(nullptr),
    resample_context(nullptr),
    input_frame(nullptr),
    output_frame(nullptr),
    packet(nullptr),
    input_filename(input_filename),
    output_filename(output_filename),
    //mutex(),
    encoder_frame_size(0),
    is_pcm_output(false),
    is_transcoding(false) {}

AudioTranscoder::~AudioTranscoder()
{
    if (input_format_context)
        avformat_close_input(&input_format_context);
    if (output_format_context)
        avformat_free_context(output_format_context);
    if (input_codec_context)
        avcodec_free_context(&input_codec_context);
    if (output_codec_context)
        avcodec_free_context(&output_codec_context);
    if (resample_context)
        swr_free(&resample_context);
    if (input_frame)
        av_frame_free(&input_frame);
    if (output_frame)
        av_frame_free(&output_frame);
    if (packet)
        av_packet_free(&packet);
}

void AudioTranscoder::open_input_file(bool is_pcm_input)
{
    if (is_pcm_input) {
        // 1. 选择正确的demuxer名称
        const char* input_format_name = nullptr;
        AVCodecID pcm_codec_id;
        switch (transcode_pcm.in_sample_fmt) {
        case AV_SAMPLE_FMT_U8:
            input_format_name = "u8";
            pcm_codec_id = AV_CODEC_ID_PCM_U8;
            break;
        case AV_SAMPLE_FMT_S16:
            input_format_name = "s16le";
            pcm_codec_id = AV_CODEC_ID_PCM_S16LE;
            break;
        case AV_SAMPLE_FMT_S32:
            input_format_name = "s32le";
            pcm_codec_id = AV_CODEC_ID_PCM_S32LE;
            break;
        case AV_SAMPLE_FMT_FLT:
            input_format_name = "f32le";
            pcm_codec_id = AV_CODEC_ID_PCM_F32LE;
            break;
        default:
            input_format_name = "s16le";
            pcm_codec_id = AV_CODEC_ID_PCM_S16LE;
            break;
        }
        const AVInputFormat* input_format = av_find_input_format(input_format_name);
        if (!input_format) {
            throw std::runtime_error(std::string("Could not find input format for PCM: ") + input_format_name);
        }

        // 2. 打开输入文件
        if (avformat_open_input(&input_format_context, input_filename.c_str(), input_format, nullptr) < 0) {
            throw std::runtime_error("Could not open PCM input file");
        }

        // 3. 查找流信息
        if (avformat_find_stream_info(input_format_context, nullptr) < 0) {
            throw std::runtime_error("Could not find stream information for PCM");
        }

        // 4. 查找音频流
        for (unsigned int i = 0; i < input_format_context->nb_streams; i++) {
            AVStream* stream = input_format_context->streams[i];
            AVCodecParameters* codec_params = stream->codecpar;
            if (codec_params->codec_type == AVMEDIA_TYPE_AUDIO) {
                input_stream = stream;
                break;
            }
        }
        if (!input_stream) {
            throw std::runtime_error("Could not find audio stream in PCM input file");
        }

        // 5. 设置参数（可选，通常 demuxer 已设置好）
        AVCodecParameters* codec_params = input_stream->codecpar;
        codec_params->codec_id = pcm_codec_id;
        codec_params->format = transcode_pcm.in_sample_fmt;
        codec_params->sample_rate = transcode_pcm.in_sample_rate;
        codec_params->ch_layout = transcode_pcm.in_layout;

        // 6. 查找解码器并初始化解码器上下文
        const AVCodec* codec = avcodec_find_decoder(codec_params->codec_id);
        if (!codec) {
            throw std::runtime_error("Could not find audio codec for PCM");
        }
        input_codec_context = avcodec_alloc_context3(codec);
        if (!input_codec_context) {
            throw std::runtime_error("Could not allocate audio codec context for PCM");
        }
        if (avcodec_parameters_to_context(input_codec_context, codec_params) < 0) {
            throw std::runtime_error("Could not copy audio codec parameters to context for PCM");
        }
        if (avcodec_open2(input_codec_context, codec, nullptr) < 0) {
            throw std::runtime_error("Could not open audio codec for PCM");
        }

        /*
        // 3. 创建音频流并设置参数
        input_stream = avformat_new_stream(input_format_context, nullptr);
        if (!input_stream) {
            throw std::runtime_error("Could not create new stream for input context");
        }
        AVCodecParameters* codec_params = input_stream->codecpar;
        codec_params->codec_type = AVMEDIA_TYPE_AUDIO;
        codec_params->codec_id = pcm_codec_id;
        codec_params->format = transcode_pcm.in_sample_fmt;
        codec_params->sample_rate = transcode_pcm.in_sample_rate;
        codec_params->ch_layout = transcode_pcm.in_layout;

        // 4. 查找解码器并初始化解码器上下文
        const AVCodec* codec = avcodec_find_decoder(codec_params->codec_id);
        if (!codec) {
            throw std::runtime_error("Could not find audio codec for PCM");
        }
        input_codec_context = avcodec_alloc_context3(codec);
        if (!input_codec_context) {
            throw std::runtime_error("Could not allocate audio codec context for PCM");
        }
        if (avcodec_parameters_to_context(input_codec_context, codec_params) < 0) {
            throw std::runtime_error("Could not copy audio codec parameters to context for PCM");
        }
        if (avcodec_open2(input_codec_context, codec, nullptr) < 0) {
            throw std::runtime_error("Could not open audio codec for PCM");
        }
        */
    }
    else {
        // 对于非PCM输入，使用 avformat_open_input 等函数自动检测
        if (avformat_open_input(&input_format_context, input_filename.c_str(), nullptr, nullptr) != 0) {
            throw std::runtime_error("Could not open input file");
        }

        if (avformat_find_stream_info(input_format_context, nullptr) < 0) {
            throw std::runtime_error("Could not find stream information");
        }

        for (unsigned int i = 0; i < input_format_context->nb_streams; i++) {
            AVStream* stream = input_format_context->streams[i];
            AVCodecParameters* codec_params = stream->codecpar;

            if (codec_params->codec_type == AVMEDIA_TYPE_AUDIO) {
                input_stream = stream;
                break;
            }
        }

        if (!input_stream) {
            throw std::runtime_error("Could not find audio stream in input file");
        }

        const AVCodec* codec = avcodec_find_decoder(input_stream->codecpar->codec_id);
        if (!codec) {
            throw std::runtime_error("Could not find audio codec");
        }

        input_codec_context = avcodec_alloc_context3(codec);
        if (!input_codec_context) {
            throw std::runtime_error("Could not allocate audio codec context");
        }

        if (avcodec_parameters_to_context(input_codec_context, input_stream->codecpar) < 0) {
            throw std::runtime_error("Could not copy audio codec parameters to context");
        }

        if (avcodec_open2(input_codec_context, codec, nullptr) < 0) {
            throw std::runtime_error("Could not open audio codec");
        }
    }
}

void AudioTranscoder::open_output_file(const char* output_suffix)
{
    avformat_alloc_output_context2(&output_format_context, nullptr, nullptr, output_filename.c_str());
    if (!output_format_context)
        throw std::runtime_error("Could not allocate output format context");
    output_stream = avformat_new_stream(output_format_context, nullptr);
    if (!output_stream)
        throw std::runtime_error("Could not allocate output stream");

    // 格式选择
    const char* codec_name = nullptr;
    if (!strcmp(output_suffix, "mp3"))
        codec_name = "libmp3lame";
    else if (!strcmp(output_suffix, "ogg"))
        codec_name = "libvorbis";
    else if (!strcmp(output_suffix, "pcm")) {
        // 设置输出格式参数
        is_pcm_output = true;
        output_codec_context = avcodec_alloc_context3(nullptr);
        if (!output_codec_context)
            throw std::runtime_error("Could not allocate output codec context for PCM");
        output_codec_context->sample_fmt = transcode_pcm.out_sample_fmt;
        output_codec_context->sample_rate = transcode_pcm.out_sample_rate;
        output_codec_context->ch_layout = transcode_pcm.out_layout;
        if (transcode_pcm.out_sample_fmt == AV_SAMPLE_FMT_S16)
            codec_name = "pcm_s16le";
        else if (transcode_pcm.out_sample_fmt == AV_SAMPLE_FMT_S32)
            codec_name = "pcm_s32le";
        else if (transcode_pcm.out_sample_fmt == AV_SAMPLE_FMT_FLT)
            codec_name = "pcm_f32le";
        else
            throw std::runtime_error("Unsupported input sample format for PCM output");
    }
    else if (!strcmp(output_suffix, "wav")) {
        if (input_codec_context->sample_fmt == AV_SAMPLE_FMT_S16)
            codec_name = "pcm_s16le";
        else if (input_codec_context->sample_fmt == AV_SAMPLE_FMT_S32)
            codec_name = "pcm_s32le";
        else if (input_codec_context->sample_fmt == AV_SAMPLE_FMT_FLT)
            codec_name = "pcm_f32le";
        else
            codec_name = "pcm_s16le";
    }
    else if (!strcmp(output_suffix, "m4a")) {
        // m4a是封装格式，编码器应为aac
        codec_name = "aac"; // 或可用的aac编码器如libfdk_aac
    }
    else {
        codec_name = output_suffix;
    }

    const AVCodec* codec = avcodec_find_encoder_by_name(codec_name);
    if (!codec)
        throw std::runtime_error("Could not find audio codec");

    // 优先用输入参数，只有不支持时才降级
    // 采样格式
    if (!is_pcm_output) {
        output_codec_context = avcodec_alloc_context3(codec);
        if (!output_codec_context)
            throw std::runtime_error("Could not allocate audio codec context");
        output_codec_context->sample_fmt = codec->sample_fmts ? codec->sample_fmts[0] : AV_SAMPLE_FMT_S16;
        if (codec->sample_fmts)
            for (const enum AVSampleFormat* p = codec->sample_fmts; *p != -1; ++p)
                if (*p == input_codec_context->sample_fmt) {
                    output_codec_context->sample_fmt = *p;
                    break;
                }

        // 采样率
        output_codec_context->sample_rate = input_codec_context->sample_rate;
        if (codec->supported_samplerates) {
            bool found = false;
            for (const int* r = codec->supported_samplerates; *r; ++r) {
                if (*r == input_codec_context->sample_rate) {
                    found = true;
                    break;
                }
            }
            if (!found)
                output_codec_context->sample_rate = codec->supported_samplerates[0];
        }

        // 通道布局
        int channels = input_codec_context->ch_layout.nb_channels > 0 ? input_codec_context->ch_layout.nb_channels : 2;
        av_channel_layout_default(&output_codec_context->ch_layout, channels);
    }

    // 码率、时间基
    output_codec_context->bit_rate = 128000;
    output_codec_context->time_base = { 1, output_codec_context->sample_rate };
    output_stream->time_base = output_codec_context->time_base;

    // 先设置参数再同步到 stream
    int ret = avcodec_open2(output_codec_context, codec, nullptr);
    if (ret < 0)
        throw std::runtime_error("Could not open audio codec");

    /*
    // 对于 ogg 格式，需要额外设置一些参数
    //if (codec_name && !strcmp(codec_name, "libvorbis")) {
        //output_codec_context->codec_tag = 0;
        //output_codec_context->flags |= AV_CODEC_FLAG_QSCALE;
        //output_codec_context->global_quality = 4;
        //output_codec_context->qcompress = 0.6;
        //output_codec_context->qmin = 0;
        //output_codec_context->qmax = 4608;
        //output_codec_context->compression_level = 10; // 10 代表无损压缩
        //// 设置 Vorbis 头信息}
        //output_stream->codecpar->codec_tag = 0;
        //output_stream->codecpar->extradata_size = 27;
        //output_stream->codecpar->extradata = (uint8_t*)av_malloc(output_stream->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
        //memset(output_stream->codecpar->extradata, 0, output_stream->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
        //AVDictionary* options = nullptr;
        //av_dict_set(&options, "vendor", "ffmpeg", 0);
        //av_dict_set(&options, "quality", "4", 0);
        //av_dict_set(&options, "compression_level", "10", 0);
        //av_dict_set(&options, "bitrate", "128k", 0);
        //av_dict_set(&options, "channels", "2", 0);
        //av_dict_set(&options, "samplerate", "44100", 0);
        //av_dict_set(&options, "codec", "libvorbis", 0);
        //av_dict_set(&options, "qmin", "0", 0);
        //av_dict_set(&options, "qmax", "4608", 0);
        //av_dict_set(&options, "qcomp", "0.6", 0);
        //av_dict_set(&options, "bass", "0", 0);
        //av_dict_set(&options, "treble", "0", 0);
        //av_dict_set(&options, "lowpass", "0", 0);
        //av_dict_set(&options, "highpass", "0", 0);
        //av_dict_set(&options, "bandpass", "0", 0);
        //av_dict_set(&options, "gain", "0", 0);
        //av_dict_set(&options, "peak_amplitude", "0.0", 0);
        //av_dict_set(&options, "replaygain_mode", "none", 0);
        //av_dict_set(&options, "replaygain_pre_amp", "0.0", 0);

        // 手动设置 frame_size
        //output_codec_context->frame_size = input_codec_context->frame_size;
    //}
    */

    // 这里在 avcodec_open2 之后读取 frame_size，如果为0则手动设为1024
    encoder_frame_size = output_codec_context->frame_size > 0 ? output_codec_context->frame_size : 1024;

    avcodec_parameters_from_context(output_stream->codecpar, output_codec_context);

    if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&output_format_context->pb, output_filename.c_str(), AVIO_FLAG_WRITE) < 0)
            throw std::runtime_error("Could not open output file");
    }
    if (!is_pcm_output) {
        ret = avformat_write_header(output_format_context, nullptr);
        if (ret < 0) {
            char errbuf[128];
            av_strerror(ret, errbuf, sizeof(errbuf));
            throw std::runtime_error(std::string("Could not write header to output file: ") + errbuf);
        }
    }
}

void AudioTranscoder::init_resample_context()
{
    resample_context = swr_alloc();
    if (!resample_context) {
        throw std::runtime_error("Could not allocate resample context");
    }

    // 设置输入参数
    av_opt_set_chlayout(resample_context, "in_chlayout", &input_stream->codecpar->ch_layout, 0);
    av_opt_set_int(resample_context, "in_sample_rate", input_stream->codecpar->sample_rate, 0);
    av_opt_set_sample_fmt(resample_context, "in_sample_fmt", input_codec_context->sample_fmt, 0);

    // 设置输出参数，全部与 output_codec_context 保持一致
    av_opt_set_chlayout(resample_context, "out_chlayout", &output_codec_context->ch_layout, 0);
    av_opt_set_int(resample_context, "out_sample_rate", output_codec_context->sample_rate, 0);
    av_opt_set_sample_fmt(resample_context, "out_sample_fmt", output_codec_context->sample_fmt, 0);

    if (swr_init(resample_context) < 0) {
        throw std::runtime_error("Could not initialize resample context");
    }
}

void AudioTranscoder::transcode_audio()
{
    input_frame = av_frame_alloc();
    output_frame = av_frame_alloc();
    packet = av_packet_alloc();
    if (!input_frame || !output_frame || !packet)
        throw std::runtime_error("Could not allocate frames and packet");

    int frame_size = encoder_frame_size;
    int channels = output_codec_context->ch_layout.nb_channels;
    AVSampleFormat sample_fmt = output_codec_context->sample_fmt;
    int sample_bytes = av_get_bytes_per_sample(sample_fmt);
    bool is_planar = av_sample_fmt_is_planar(sample_fmt);
    int planes = is_planar ? channels : 1;
    int max_cache_samples = frame_size * 10;
    std::vector<uint8_t*> cache_data(planes);
    for (int ch = 0; ch < planes; ++ch)
        cache_data[ch] = (uint8_t*)av_malloc(max_cache_samples * sample_bytes * (is_planar ? 1 : channels));
    int cache_samples = 0;
    int64_t next_pts = 0;

    // 主循环：解码、重采样、缓存、分帧、编码/写包
    while (av_read_frame(input_format_context, packet) >= 0) {
        if (packet->stream_index != input_stream->index) {
            av_packet_unref(packet);
            continue;
        }
        avcodec_send_packet(input_codec_context, packet);
        while (avcodec_receive_frame(input_codec_context, input_frame) == 0) {
            int max_convert = max_cache_samples - cache_samples;
            std::vector<uint8_t*> temp_data(planes);
            for (int ch = 0; ch < planes; ++ch)
                temp_data[ch] = cache_data[ch] + cache_samples * sample_bytes * (is_planar ? 1 : channels);
            int converted = swr_convert(resample_context,
                temp_data.data(),
                //output_frame->nb_samples,
                max_convert,
                (const uint8_t**)input_frame->extended_data,
                input_frame->nb_samples);
            if (converted < 0)
                throw std::runtime_error("Error resampling");
            cache_samples += converted;
            // 分帧处理
            while (cache_samples >= frame_size) {
                // 编码流程
                output_frame->nb_samples = frame_size;
                output_frame->format = sample_fmt;
                output_frame->ch_layout = output_codec_context->ch_layout;
                output_frame->sample_rate = output_codec_context->sample_rate;
                av_frame_get_buffer(output_frame, 0);
                av_frame_make_writable(output_frame);
                if (is_planar) {
                    for (int ch = 0; ch < channels; ++ch)
                        memcpy(output_frame->extended_data[ch], cache_data[ch], frame_size * sample_bytes);
                }
                else {
                    memcpy(output_frame->extended_data[0], cache_data[0], frame_size * channels * sample_bytes);
                }
                output_frame->pts = next_pts;
                next_pts += output_frame->nb_samples;
                avcodec_send_frame(output_codec_context, output_frame);
                while (avcodec_receive_packet(output_codec_context, packet) == 0) {
                    packet->stream_index = output_stream->index;
                    av_packet_rescale_ts(packet, output_codec_context->time_base, output_stream->time_base);
                    av_interleaved_write_frame(output_format_context, packet);
                    av_packet_unref(packet);
                }
                // 移动缓存
                for (int ch = 0; ch < planes; ++ch)
                    memmove(cache_data[ch], cache_data[ch] + frame_size * sample_bytes, (cache_samples - frame_size) * sample_bytes);
                cache_samples -= frame_size;
            }
        }
        av_packet_unref(packet);
    }
    // 处理剩余采样，最后一帧补零
    if (cache_samples > 0) {
        int send_samples = cache_samples;
        output_frame->nb_samples = send_samples;
        output_frame->format = sample_fmt;
        output_frame->ch_layout = output_codec_context->ch_layout;
        output_frame->sample_rate = output_codec_context->sample_rate;
        av_frame_get_buffer(output_frame, 0);
        av_frame_make_writable(output_frame);
        if (is_planar) {
            for (int ch = 0; ch < channels; ++ch) {
                memcpy(output_frame->extended_data[ch], cache_data[ch], cache_samples * sample_bytes);
            }
        }
        else {
            memcpy(output_frame->extended_data[0], cache_data[0], cache_samples * channels * sample_bytes);
        }
        output_frame->pts = next_pts;
        avcodec_send_frame(output_codec_context, output_frame);
        while (avcodec_receive_packet(output_codec_context, packet) == 0) {
            packet->stream_index = output_stream->index;
            av_packet_rescale_ts(packet, output_codec_context->time_base, output_stream->time_base);
            av_interleaved_write_frame(output_format_context, packet);
            av_packet_unref(packet);
        }
    }
    avcodec_send_frame(output_codec_context, nullptr);
    while (avcodec_receive_packet(output_codec_context, packet) == 0) {
        packet->stream_index = output_stream->index;
        av_packet_rescale_ts(packet, output_codec_context->time_base, output_stream->time_base);
        av_interleaved_write_frame(output_format_context, packet);
        av_packet_unref(packet);
    }
    for (int ch = 0; ch < planes; ++ch)
        av_free(cache_data[ch]);
    av_write_trailer(output_format_context);
    av_frame_free(&input_frame);
    av_frame_free(&output_frame);
    av_packet_free(&packet);
}

void AudioTranscoder::transcode_audio_pcm()
{
    // 初始化重采样上下文
    if (resample_context) {
        swr_free(&resample_context);
        resample_context = nullptr;
    }

    resample_context = swr_alloc();
    if (!resample_context) {
        throw std::runtime_error("Could not allocate resample context");
    }
    av_opt_set_chlayout(resample_context, "in_chlayout", &input_stream->codecpar->ch_layout, 0);
    av_opt_set_int(resample_context, "in_sample_rate", input_stream->codecpar->sample_rate, 0);
    av_opt_set_sample_fmt(resample_context, "in_sample_fmt", input_codec_context->sample_fmt, 0);
    av_opt_set_chlayout(resample_context, "out_chlayout", &transcode_pcm.out_layout, 0);
    av_opt_set_int(resample_context, "out_sample_rate", transcode_pcm.out_sample_rate, 0);
    av_opt_set_sample_fmt(resample_context, "out_sample_fmt", transcode_pcm.out_sample_fmt, 0);
    if (swr_init(resample_context) < 0) {
        throw std::runtime_error("Could not initialize resample context");
    }

    QDir dir(QFileInfo(output_filename.c_str()).absolutePath());
    if (!dir.exists()) {
        qDebug() << "Directory does not exist:" << dir.absolutePath();
        throw std::runtime_error("Directory does not exist");
    }

    QFileInfo dirInfo(dir.absolutePath());
    if (!dirInfo.isWritable()) {
        qDebug() << "Directory is not writable:" << dirInfo.absolutePath();
        throw std::runtime_error("Directory is not writable");
    }
    // 打开输出文件（二进制写）
    qDebug() << "output_filename: " << output_filename.c_str();

    // 使用Qt转换为本地编码，避免编码问题
    QByteArray localFileName = QString::fromUtf8(output_filename.c_str()).toLocal8Bit(); // 之前构建的 output_filename 已是 UTF-8 所以用 fromUtf8 函数

    qDebug() << "localFileName: " << localFileName.constData();
    // 使用Qt的文件操作函数来打开文件
    //QFile file(localFileName);
    //if (!file.open(QIODevice::WriteOnly)) {
    //    qDebug() << "Failed to open file:" << localFileName << "Error:" << file.errorString();
    //    return;
    //    throw std::runtime_error("Could not open output PCM file");
    //}

    qDebug() << "File opened successfully:" << localFileName.constData();

    // 使用FILE*打开文件
    FILE* outfile = fopen(localFileName.constData(), "wb");
    qDebug() << "output pointer: " << outfile;
    if (!outfile) {
        qDebug() << "fopen failed, localFileName:" << localFileName;
        throw std::runtime_error("Could not open output PCM file");
    }

    input_frame = av_frame_alloc();
    if (!input_frame)
        throw std::runtime_error("Could not allocate input frame");
    output_frame = av_frame_alloc();
    if (!output_frame)
        throw std::runtime_error("Could not allocate output frame");
    packet = av_packet_alloc();
    if (!packet)
        throw std::runtime_error("Could not allocate packet");

    int out_channels = transcode_pcm.out_layout.nb_channels;
    int out_sample_rate = transcode_pcm.out_sample_rate;
    AVSampleFormat out_sample_fmt = transcode_pcm.out_sample_fmt;
    int out_bytes_per_sample = av_get_bytes_per_sample(out_sample_fmt);
    bool out_is_planar = av_sample_fmt_is_planar(out_sample_fmt);
    int out_planes = out_is_planar ? out_channels : 1;
    int max_out_samples = 4096;

    // 分配输出缓冲区
    uint8_t** out_data = nullptr;
    int out_linesize = 0;
    av_samples_alloc_array_and_samples(&out_data,
        &out_linesize,
        out_channels,
        max_out_samples,
        out_sample_fmt, 0);

    // 主循环：解码、重采样、写 PCM
    while (av_read_frame(input_format_context, packet) >= 0) {
        if (packet->stream_index != input_stream->index) {
            av_packet_unref(packet);
            continue;
        }
        avcodec_send_packet(input_codec_context, packet);
        while (avcodec_receive_frame(input_codec_context, input_frame) == 0) {
            int in_samples = input_frame->nb_samples;
            int out_samples = swr_convert(resample_context,
                out_data,
                max_out_samples,
                (const uint8_t**)input_frame->extended_data,
                in_samples);
            if (out_samples < 0) {
                fclose(outfile);
                av_freep(&out_data[0]);
                av_freep(&out_data);
                throw std::runtime_error("Error during resampling");
            }
            // 写入PCM数据
            int data_size = out_samples * out_channels * out_bytes_per_sample;
            if (out_is_planar) {
                // 逐通道写入
                for (int i = 0; i < out_samples; ++i) {
                    for (int ch = 0; ch < out_channels; ++ch) {
                        fwrite(out_data[ch] + i * out_bytes_per_sample, 1, out_bytes_per_sample, outfile);
                    }
                }
            }
            else {
                fwrite(out_data[0], 1, data_size, outfile);
            }
        }
        av_packet_unref(packet);
    }

    // 释放资源
    fclose(outfile);
    av_freep(&out_data[0]);
    av_freep(&out_data);
    av_frame_free(&input_frame);
    av_frame_free(&output_frame);
    av_packet_free(&packet);
}

std::string get_file_suffix(const std::string& output_filename)
{
    // 找到最后一个点的位置
    size_t pos = output_filename.find_last_of('.');
    if (pos != std::string::npos) {
        // 提取后缀名
        return output_filename.substr(pos + 1);
    }
    return ""; // 如果没有找到点，返回空字符串
}

void AudioTranscoder::transcode()
{
    try {
        //if (is_transcoding.exchange(true)) {
        //    // 如果 is_transcoding 原本为 true，则直接返回
        //    return;
        //}
        // 设置转码状态
        //is_transcoding.store(true);
        open_input_file(transcode_pcm.is_pcm_input);
        std::string outfile_suffix = get_file_suffix(output_filename);
        open_output_file(outfile_suffix.c_str());
        init_resample_context();
        is_pcm_output ? transcode_audio_pcm() : transcode_audio();
        // 如果你需要毫秒级的时间戳
        auto now = std::chrono::high_resolution_clock::now();
        auto duration = now.time_since_epoch();
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
        emit transcodeFinished(millis);
        // 重置转码状态
        is_transcoding.store(false);
    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        // 重置转码状态
        is_transcoding.store(false);
        throw;
    }
}

void AudioTranscoder::start()
{
    if (is_transcoding.exchange(true)) {
        // 如果 is_transcoding 原本为 true，则直接返回
        return;
    }
    std::thread(&AudioTranscoder::transcode, this).detach();
}

